@johnhenry/sitefile 0.0.0-stage → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +152 -0
- package/LICENSE +21 -0
- package/README.md +513 -2
- package/lib/src/archive-writers.d.ts +31 -0
- package/lib/src/archive-writers.js +197 -0
- package/lib/src/attest.d.ts +126 -0
- package/lib/src/attest.js +220 -0
- package/lib/src/bake.d.ts +74 -0
- package/lib/src/bake.js +372 -0
- package/lib/src/base-image.d.ts +76 -0
- package/lib/src/base-image.js +138 -0
- package/lib/src/build-args.d.ts +26 -0
- package/lib/src/build-args.js +164 -0
- package/lib/src/cache-limit.d.ts +54 -0
- package/lib/src/cache-limit.js +239 -0
- package/lib/src/casefold-data.d.ts +2 -0
- package/lib/src/casefold-data.js +217 -0
- package/lib/src/cbor.d.ts +39 -0
- package/lib/src/cbor.js +174 -0
- package/lib/src/checklinks.d.ts +42 -0
- package/lib/src/checklinks.js +120 -0
- package/lib/src/cli/bake.d.ts +2 -0
- package/lib/src/cli/bake.js +179 -0
- package/lib/src/cli/build-image.d.ts +21 -0
- package/lib/src/cli/build-image.js +42 -0
- package/lib/src/cli/cache.d.ts +8 -0
- package/lib/src/cli/cache.js +119 -0
- package/lib/src/cli/common.d.ts +29 -0
- package/lib/src/cli/common.js +100 -0
- package/lib/src/cli/git-context.d.ts +18 -0
- package/lib/src/cli/git-context.js +48 -0
- package/lib/src/cli/images.d.ts +6 -0
- package/lib/src/cli/images.js +285 -0
- package/lib/src/cli/index.d.ts +10 -0
- package/lib/src/cli/index.js +95 -0
- package/lib/src/cli/network.d.ts +34 -0
- package/lib/src/cli/network.js +56 -0
- package/lib/src/cli/outdated.d.ts +5 -0
- package/lib/src/cli/outdated.js +99 -0
- package/lib/src/cli/registry.d.ts +2 -0
- package/lib/src/cli/registry.js +127 -0
- package/lib/src/cli/serve-worker.d.ts +2 -0
- package/lib/src/cli/serve-worker.js +42 -0
- package/lib/src/cli/servers.d.ts +15 -0
- package/lib/src/cli/servers.js +467 -0
- package/lib/src/cli/vendor.d.ts +2 -0
- package/lib/src/cli/vendor.js +97 -0
- package/lib/src/cli/watch.d.ts +26 -0
- package/lib/src/cli/watch.js +81 -0
- package/lib/src/cli.d.ts +12 -0
- package/lib/src/cli.js +522 -0
- package/lib/src/csv.d.ts +27 -0
- package/lib/src/csv.js +117 -0
- package/lib/src/deflate.d.ts +76 -0
- package/lib/src/deflate.js +604 -0
- package/lib/src/digest.d.ts +3 -0
- package/lib/src/digest.js +7 -0
- package/lib/src/errors.d.ts +56 -0
- package/lib/src/errors.js +29 -0
- package/lib/src/executor.d.ts +393 -0
- package/lib/src/executor.js +2201 -0
- package/lib/src/explain.d.ts +64 -0
- package/lib/src/explain.js +445 -0
- package/lib/src/export-formats.d.ts +23 -0
- package/lib/src/export-formats.js +63 -0
- package/lib/src/exporter.d.ts +103 -0
- package/lib/src/exporter.js +676 -0
- package/lib/src/fingerprint.d.ts +40 -0
- package/lib/src/fingerprint.js +168 -0
- package/lib/src/frontmatter.d.ts +22 -0
- package/lib/src/frontmatter.js +45 -0
- package/lib/src/index.d.ts +13 -0
- package/lib/src/index.js +13 -0
- package/lib/src/language/ast.d.ts +360 -0
- package/lib/src/language/ast.js +57 -0
- package/lib/src/language/parser.d.ts +3 -0
- package/lib/src/language/parser.js +612 -0
- package/lib/src/language/scanner.d.ts +110 -0
- package/lib/src/language/scanner.js +449 -0
- package/lib/src/language/validate.d.ts +13 -0
- package/lib/src/language/validate.js +367 -0
- package/lib/src/links.d.ts +79 -0
- package/lib/src/links.js +583 -0
- package/lib/src/lint.d.ts +10 -0
- package/lib/src/lint.js +223 -0
- package/lib/src/markdown.d.ts +29 -0
- package/lib/src/markdown.js +612 -0
- package/lib/src/media.d.ts +82 -0
- package/lib/src/media.js +650 -0
- package/lib/src/memo.d.ts +57 -0
- package/lib/src/memo.js +93 -0
- package/lib/src/oci.d.ts +178 -0
- package/lib/src/oci.js +380 -0
- package/lib/src/outdated.d.ts +46 -0
- package/lib/src/outdated.js +195 -0
- package/lib/src/pages.d.ts +10 -0
- package/lib/src/pages.js +54 -0
- package/lib/src/paths.d.ts +39 -0
- package/lib/src/paths.js +101 -0
- package/lib/src/planner.d.ts +297 -0
- package/lib/src/planner.js +410 -0
- package/lib/src/plugins/cache.d.ts +96 -0
- package/lib/src/plugins/cache.js +325 -0
- package/lib/src/plugins/exec.d.ts +51 -0
- package/lib/src/plugins/exec.js +144 -0
- package/lib/src/plugins/host.d.ts +75 -0
- package/lib/src/plugins/host.js +277 -0
- package/lib/src/plugins/wasm.d.ts +23 -0
- package/lib/src/plugins/wasm.js +249 -0
- package/lib/src/profile.d.ts +42 -0
- package/lib/src/profile.js +68 -0
- package/lib/src/ref.d.ts +40 -0
- package/lib/src/ref.js +79 -0
- package/lib/src/registry-auth.d.ts +32 -0
- package/lib/src/registry-auth.js +151 -0
- package/lib/src/registry-cache.d.ts +71 -0
- package/lib/src/registry-cache.js +333 -0
- package/lib/src/registry-ops.d.ts +51 -0
- package/lib/src/registry-ops.js +248 -0
- package/lib/src/registry.d.ts +115 -0
- package/lib/src/registry.js +524 -0
- package/lib/src/render.d.ts +134 -0
- package/lib/src/render.js +576 -0
- package/lib/src/resources/archive.d.ts +11 -0
- package/lib/src/resources/archive.js +306 -0
- package/lib/src/resources/bundle-data.d.ts +16 -0
- package/lib/src/resources/bundle-data.js +50 -0
- package/lib/src/resources/convert.d.ts +12 -0
- package/lib/src/resources/convert.js +63 -0
- package/lib/src/resources/documents.d.ts +35 -0
- package/lib/src/resources/documents.js +122 -0
- package/lib/src/resources/git.d.ts +103 -0
- package/lib/src/resources/git.js +720 -0
- package/lib/src/resources/https.d.ts +74 -0
- package/lib/src/resources/https.js +413 -0
- package/lib/src/resources/ignore.d.ts +33 -0
- package/lib/src/resources/ignore.js +119 -0
- package/lib/src/resources/local.d.ts +64 -0
- package/lib/src/resources/local.js +248 -0
- package/lib/src/resources/lockfile.d.ts +52 -0
- package/lib/src/resources/lockfile.js +172 -0
- package/lib/src/resources/netpolicy.d.ts +6 -0
- package/lib/src/resources/netpolicy.js +82 -0
- package/lib/src/resources/network.d.ts +70 -0
- package/lib/src/resources/network.js +304 -0
- package/lib/src/resources/types.d.ts +69 -0
- package/lib/src/resources/types.js +13 -0
- package/lib/src/resources/vendor.d.ts +94 -0
- package/lib/src/resources/vendor.js +296 -0
- package/lib/src/resources/wbn-reader.d.ts +44 -0
- package/lib/src/resources/wbn-reader.js +302 -0
- package/lib/src/schema.d.ts +25 -0
- package/lib/src/schema.js +169 -0
- package/lib/src/secrets.d.ts +21 -0
- package/lib/src/secrets.js +103 -0
- package/lib/src/serve-rules.d.ts +29 -0
- package/lib/src/serve-rules.js +123 -0
- package/lib/src/server.d.ts +45 -0
- package/lib/src/server.js +246 -0
- package/lib/src/servers.d.ts +85 -0
- package/lib/src/servers.js +225 -0
- package/lib/src/site.d.ts +60 -0
- package/lib/src/site.js +169 -0
- package/lib/src/store.d.ts +151 -0
- package/lib/src/store.js +596 -0
- package/lib/src/tree.d.ts +50 -0
- package/lib/src/tree.js +134 -0
- package/lib/src/values.d.ts +7 -0
- package/lib/src/values.js +37 -0
- package/lib/src/vendor.d.ts +19 -0
- package/lib/src/vendor.js +145 -0
- package/lib/src/watch.d.ts +44 -0
- package/lib/src/watch.js +137 -0
- package/lib/src/wbn.d.ts +26 -0
- package/lib/src/wbn.js +241 -0
- package/lib/src/yaml.d.ts +34 -0
- package/lib/src/yaml.js +562 -0
- package/package.json +59 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.0.1 (2026-11-08)
|
|
4
|
+
|
|
5
|
+
- **`serve` serves archive files** (johnhenry/sitefile#155): `sitefile serve
|
|
6
|
+
site.zip` (and `serve -d`) serves a zip, tar, tar.gz/tgz, Web Bundle or OCI
|
|
7
|
+
image archive (`build -o x.oci.tar`, `save`) the way it serves a directory.
|
|
8
|
+
The format comes from the bytes; a path-like argument that is a file is an
|
|
9
|
+
archive, and a bare name is an archive file when no image has that name.
|
|
10
|
+
Zip, tar and wbn are extracted with the default archive limits and served
|
|
11
|
+
without hidden files (as a directory is); an OCI archive serves its first
|
|
12
|
+
image as the store would, with every blob checked against its digest. The
|
|
13
|
+
file is read again on every start and `server restart`. Server records gain
|
|
14
|
+
`{"kind": "archive", "path": …}` (older records load unchanged); Rust adds
|
|
15
|
+
`ServerSource::Archive`, `servers::load_archive_tree` and
|
|
16
|
+
`load_archive_tree_with`, with every existing signature unchanged. A file
|
|
17
|
+
that is not an archive is `E_TYPE` naming it. docs/CLI.md, "Site servers".
|
|
18
|
+
- **Explicit network settings: proxy, host rules, connect/read timeouts**
|
|
19
|
+
(johnhenry/sitefile#156), for networks that need a proxy and for sitefile
|
|
20
|
+
Desktop's Settings screen. `--proxy` / `SITEFILE_PROXY` (an `http://` proxy:
|
|
21
|
+
a CONNECT tunnel for https, absolute form for http; `HTTP(S)_PROXY` is still
|
|
22
|
+
never read), `--no-proxy` / `SITEFILE_NO_PROXY` (`NO_PROXY` syntax),
|
|
23
|
+
`--allow-hosts` / `SITEFILE_ALLOW_HOSTS` and `--deny-hosts` /
|
|
24
|
+
`SITEFILE_DENY_HOSTS` (checked on every hop, registries included; deny beats
|
|
25
|
+
allow; the new code `E_HOST_BLOCKED` names the rule), and `--connect-timeout`
|
|
26
|
+
/ `--read-timeout` / `SITEFILE_FETCH_TIMEOUT`, on `build`, `validate`,
|
|
27
|
+
`inspect`, `graph`, `why`, `pull`, `push`, `vendor` and `outdated`. A proxy
|
|
28
|
+
never widens the fetch policy: the target is resolved and checked against
|
|
29
|
+
the private-address rule before the proxy is asked. Embedders pass the same
|
|
30
|
+
settings as `FetchPolicy.network` / `RegistryOptions.network`
|
|
31
|
+
(`NetworkSettings`, additive in both implementations). docs/CLI.md,
|
|
32
|
+
"Network"; `test/network.test.ts`, `rust/src/resources/network.rs`, and the
|
|
33
|
+
`net-proxy*`, `net-no-proxy`, `net-allow-hosts` and `net-deny-hosts`
|
|
34
|
+
conformance cases. Added in c131eb3 (#162).
|
|
35
|
+
|
|
36
|
+
- **Library API for embedders** (johnhenry/sitefile#153), found by embedding
|
|
37
|
+
the crate in sitefile Desktop. Rust: `servers::serve_detached`,
|
|
38
|
+
`restart_detached`, `start_detached`, `stop_server`, `resolve_source`,
|
|
39
|
+
`parse_publish` and `DetachedServe` (the CLI's `serve -d`, `server restart`
|
|
40
|
+
and `server stop` now call them); `executor::store_build_as_image` with
|
|
41
|
+
`ImageInfo` and `StoredImage` (what `build -t` calls);
|
|
42
|
+
`BuildOptions::store_home`, so `FROM <local image>`, `BASE` and the wasm
|
|
43
|
+
module cache use an embedder's store instead of `$SITEFILE_HOME`;
|
|
44
|
+
`BuildOptions::cancel` with `CancelToken`, checked between imports, stages,
|
|
45
|
+
operations and plugin or tool calls, failing with the new code
|
|
46
|
+
`E_CANCELLED`; detached workers are reaped on a background thread, so a
|
|
47
|
+
long-lived host can stop them without waiting out the grace period.
|
|
48
|
+
Both implementations: TRANSFORM cache entries record their PLUGIN or TOOL
|
|
49
|
+
(`"plugin"`, same bytes in both; older entries are still read, keys are
|
|
50
|
+
unchanged), with `usage_by_plugin`/`usageByPlugin`,
|
|
51
|
+
`prune_plugin`/`prunePlugin` and `sitefile cache prune --plugin <name>`; the
|
|
52
|
+
`E_UNSUPPORTED` error of a PLUGIN or TOOL that is not allowed carries
|
|
53
|
+
`needs` (kind, name, flag), with the message unchanged. CLI output is
|
|
54
|
+
otherwise unchanged. docs/RUST.md, "Embedding the crate";
|
|
55
|
+
`rust/tests/embed.rs`. Added in e0c555d (#154).
|
|
56
|
+
|
|
57
|
+
- **`EXPORT … AS wbn COMPRESSION gzip`** (johnhenry/sitefile#143): a Web Bundle
|
|
58
|
+
export can now be gzip(`application/webbundle`), the `.wbn` archive format of
|
|
59
|
+
`@johnhenry/packfile` (`toArchive`/`fromArchive`) and `@johnhenry/fileable`
|
|
60
|
+
(`encode="wbn"`). `COMPRESSION` used to be `E_VALIDATION` on anything but
|
|
61
|
+
`oci`; it now applies to `oci` and `wbn`, and on `wbn` defaults to `none`, so
|
|
62
|
+
existing exports are byte-for-byte unchanged. The gzip layer only wraps the
|
|
63
|
+
finished bundle and uses the shared deterministic encoder (`src/deflate.ts`,
|
|
64
|
+
`rust/src/deflate.rs`), so both CLIs write identical bytes. On the CLI,
|
|
65
|
+
`-o site.wbn.gz` selects a gzipped wbn (also for `sitefile save`), the
|
|
66
|
+
default destination of such a Sitefile is `dist.wbn.gz`, and the new
|
|
67
|
+
`--compression gzip|none` overrides `EXPORT … COMPRESSION` for the export's
|
|
68
|
+
format (oci or wbn; any other format is a usage error); `--oci-compression`
|
|
69
|
+
stays as the oci-only spelling. A Sitefile's `COMPRESSION` belongs to its own
|
|
70
|
+
`AS` format: `--format wbn` on an `AS oci COMPRESSION …` Sitefile does not
|
|
71
|
+
inherit it. `test/packfile-interop.test.ts` now reads a gzip export built with
|
|
72
|
+
`BASE https://packfile.invalid/` through plain `fromArchive(buffer)`; new
|
|
73
|
+
conformance cases compare the bytes of both implementations. Added in
|
|
74
|
+
3c537de (#149).
|
|
75
|
+
|
|
76
|
+
- **Example: a fileable plugin for TRANSFORM** (`examples/fileable/`,
|
|
77
|
+
johnhenry/sitefile#145). A JavaScript plugin renders a `@johnhenry/fileable`
|
|
78
|
+
tree into the build with fileable's in-memory `toFiles()` and returns
|
|
79
|
+
`{ files }`, so a JSX file tree needs no directory or zip on disk in
|
|
80
|
+
between. fileable stays out of Sitefile's dependencies: it is a
|
|
81
|
+
devDependency, and `examples/fileable/vendor.mjs` copies the files its
|
|
82
|
+
browser entry point loads into the plugin folder (gitignored; nothing
|
|
83
|
+
generated is committed), the only folder a plugin can read. Its `cmd`
|
|
84
|
+
attribute and other features that need files, processes or the environment
|
|
85
|
+
fail with a clear `E_PLUGIN`. Checked by `npm run examples` and by
|
|
86
|
+
conformance (both CLIs). docs/PLUGINS.md, "Example: rendering a fileable
|
|
87
|
+
tree". Added in 0b5c4b3 (#147).
|
|
88
|
+
|
|
89
|
+
- **`EXPORT … AS wbn` bakes HEADER and exact REDIRECT rules into the bundle's
|
|
90
|
+
responses** (johnhenry/sitefile#144, #150). Each response gets the headers of the
|
|
91
|
+
`/_headers` blocks matching its URL, with `sitefile serve`'s matching
|
|
92
|
+
(`serve-rules.ts`; a directory URL like `<base>docs/` matches with its
|
|
93
|
+
slash and gets its own response when its headers differ). Exact-path
|
|
94
|
+
`/_redirects` rules with a 3xx status become responses with that status, a
|
|
95
|
+
`location` and an empty body, in `serve`'s order (a forced `301!` replaces
|
|
96
|
+
the file; other rules apply only where `serve` would find nothing). Splats,
|
|
97
|
+
`200` rewrites and `404` rules stay in `/_redirects`, which, like
|
|
98
|
+
`/_headers`, is still in the bundle. Bundles of trees without those files
|
|
99
|
+
are byte-identical to before. packfile's `createWebBundleRouter()` now
|
|
100
|
+
answers with the HEADER values and redirects (`test/packfile-interop.test.ts`);
|
|
101
|
+
conformance cases `ok-wbn-rules` and `ok-wbn-rules-files` compare both
|
|
102
|
+
implementations' bytes. The TypeScript `headersFor` no longer drops a
|
|
103
|
+
header named `__proto__` (the Rust port never did); this also
|
|
104
|
+
changes the TypeScript `sitefile serve`, which now sends such a header as
|
|
105
|
+
the Rust binary does. Added in 429ab24 (#150).
|
|
106
|
+
|
|
107
|
+
## 0.0.0 — first npm release (2026-11-06)
|
|
108
|
+
|
|
109
|
+
`@johnhenry/sitefile` is a new package: Sitefile was never published to npm
|
|
110
|
+
under any name, and `0.0.0` is its first version. It joins the @johnhenry
|
|
111
|
+
family as its static build orchestrator, next to `@johnhenry/fileable` (file
|
|
112
|
+
trees in JSX) and `@johnhenry/packfile` (the Web Bundle reader and server).
|
|
113
|
+
|
|
114
|
+
- **Published as `@johnhenry/sitefile`** (was `sitefile`, `private: true`,
|
|
115
|
+
`0.1.0` in `package.json` only). The tarball ships `lib/src/` (compiled by
|
|
116
|
+
`prepack`, no source maps), the README, `LICENSE` and this file; it has no
|
|
117
|
+
runtime dependencies. The Rust port stays at `0.1.0` in `rust/Cargo.toml`
|
|
118
|
+
and is not published (johnhenry/sitefile#69).
|
|
119
|
+
- **MIT `LICENSE` file added.** `package.json` and `rust/Cargo.toml` already
|
|
120
|
+
said MIT. See johnhenry/sitefile#69.
|
|
121
|
+
- **Node floor raised from 22 to 26** (`engines`, `.nvmrc`, CI), the family
|
|
122
|
+
floor. The suite passed unchanged on Node 26.
|
|
123
|
+
- **CI on every push and pull request** (johnhenry/sitefile#67): typecheck,
|
|
124
|
+
tests and the examples smoke test (`npm run examples`), the Rust
|
|
125
|
+
fmt/build/test (clippy non-blocking until triaged), conformance between the
|
|
126
|
+
two implementations with the release binary, the VS Code extension and
|
|
127
|
+
tree-sitter grammar tests, actionlint, and the family's workflow lint.
|
|
128
|
+
`publish.yml` publishes from `main` through npm trusted publishing.
|
|
129
|
+
- **Interop with `@johnhenry/packfile` is tested**
|
|
130
|
+
(`test/packfile-interop.test.ts`, packfile as a devDependency only): packfile
|
|
131
|
+
reads a Sitefile `.wbn` back into exactly the exported files and serves it,
|
|
132
|
+
and its `fromArchive()` reads the same bundle once gzipped. The other
|
|
133
|
+
direction, importing gzip-wrapped bundles from fileable or packfile with
|
|
134
|
+
`AS tree`, is johnhenry/sitefile#141.
|
|
135
|
+
- **Fixed: a replaced archive destination went unnoticed on Linux.** Before
|
|
136
|
+
renaming the new archive into place, `exportFile` (and the Rust
|
|
137
|
+
`export_file`) checked that the existing destination was still the file
|
|
138
|
+
they inspected by device and inode number only. Linux often gives a file
|
|
139
|
+
created right after an unlink the same inode number, so a destination
|
|
140
|
+
swapped mid-export passed the check and was replaced. The check now also
|
|
141
|
+
compares size and nanosecond `ctime`. Found by the new CI's first Linux
|
|
142
|
+
run; the existing test only ever passed on macOS. Fixed in 0e0a1a1 (#142).
|
|
143
|
+
- **Fixed: a case-only collision inside one directory had no source line.**
|
|
144
|
+
Two names that differ only in case in a directory read by `COPY` (possible
|
|
145
|
+
on a case-sensitive file system) failed with `E_PATH_COLLISION` but without
|
|
146
|
+
the instruction's line; both implementations now report it. Its test only
|
|
147
|
+
runs on case-sensitive file systems, so it had never run. Fixed in 0e0a1a1
|
|
148
|
+
(#142).
|
|
149
|
+
- **Docs:** README badges, `## Contents`, `## Install`, `## Adding a new
|
|
150
|
+
plugin`, `## Security model` (the former "Safety defaults", with what stays
|
|
151
|
+
the user's responsibility), `## Family`; `examples/README.md`;
|
|
152
|
+
`AGENTS.md` reshaped into the family playbook with `CLAUDE.md` as a symlink.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 John Henry
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|